package com.our123.cms.service;

import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.mail.javamail.MimeMessagePreparator;
import org.springframework.stereotype.Service;

import com.mobirit.mttools.util.ValidatorUtil;
import com.mobirit.mttools.util.queue.BaseQueue;
import com.mobirit.mttools.util.queue.DefaultQueueHandlerManager;
import com.mobirit.mttools.util.queue.QueueHandler;
import com.mobirit.mttools.util.queue.QueueHandlerManager;
import com.our123.cms.entity.main.CmsSite;
import com.our123.cms.entity.main.EmailConfig;
import com.our123.cms.manager.main.CmsSiteMng;
import com.our123.common.email.EmailSender;
import com.our123.common.email.MessageTemplate;

@Service
public class EmailSendQueueImpl implements EmailSendQueue, ApplicationListener<ApplicationEvent> {
	private static final int QUEUE_SIZE = 1000;
	private static final int CHECK_READ_INTERVAL = 1;
	private static final int DATA_TIMEOUT = 3600;
	private static final int HANDLER_THREAD_NUM = 3;

	//队列参数
	private BaseQueue<Object> emailSendQueue;
	private QueueHandlerManager<Object> emailSendQueueManager;

	//业务参数
	private EmailSender emailSender;

	public void send(String email, String subject, String content, Map<String, String> param) {
		if (emailSender == null) {
			init();
		}
		boolean isEmail = ValidatorUtil.isEmail(email);
		if (isEmail) {
			Map<String, MessageTemplate> data = new HashMap<String, MessageTemplate>();
			//组织邮件内容
			for (String key : param.keySet()) {
				content = StringUtils.replace(content, "${" + key + "}", param.get(key));
			}
			//构建邮件模板对象
			MessageTemplate template = new MessageTemplate(subject, content);
			data.put(email, template);
			//添加到邮件发送队列
			try {
				emailSendQueue.addData(data);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	public void onApplicationEvent(ApplicationEvent event) {
		try {
			if (event instanceof ContextRefreshedEvent) {
				queue();
				start();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void init() {
		CmsSite site = cmsSiteMng.getList().get(0);
		//发送包含新密码的电子邮件
		EmailConfig emailConfig = site.getConfig().getEmailConfig();
		//构造邮件发送者
		emailSender = new EmailSender(emailConfig.getHost(), emailConfig.getEncoding(), emailConfig.getUsername(), emailConfig.getPassword(),
				emailConfig.getPersonal());
	}

	private void queue() throws Exception {
		this.emailSendQueue = new BaseQueue<Object>();
		this.emailSendQueue.setQueueSize(QUEUE_SIZE);
		this.emailSendQueue.setCheckReadInterval(CHECK_READ_INTERVAL);
		this.emailSendQueue.setDataTimeout(DATA_TIMEOUT);
		this.emailSendQueue.initialize();
	}

	private void start() throws Exception {
		this.emailSendQueueManager = new DefaultQueueHandlerManager<Object>();
		this.emailSendQueueManager.setQueue(this.emailSendQueue);
		for (int i = 0; i < HANDLER_THREAD_NUM; ++i) {
			EmailSendHandler emailSendHandler = new EmailSendHandler();
			this.emailSendQueueManager.addQueueHandler(emailSendHandler);
		}
		this.emailSendQueueManager.initialize();
		this.emailSendQueue.startup();
		this.emailSendQueueManager.startup();
	}

	class EmailSendHandler implements QueueHandler<Object> {
		@SuppressWarnings("unchecked")
		public void handle(Object obj) throws Exception {
			Map<String, MessageTemplate> data = (Map<String, MessageTemplate>) obj;
			for (String email : data.keySet()) {
				final String to = email;
				final MessageTemplate tpl = data.get(email);
				//构建实际发送对象
				JavaMailSenderImpl sender = new JavaMailSenderImpl();
				sender.setHost(emailSender.getHost());
				sender.setUsername(emailSender.getUsername());
				sender.setPassword(emailSender.getPassword());
				sender.send(new MimeMessagePreparator() {
					public void prepare(MimeMessage mimeMessage) throws MessagingException, UnsupportedEncodingException {
						MimeMessageHelper msg = new MimeMessageHelper(mimeMessage, false, emailSender.getEncoding());
						msg.setSubject(tpl.getSubject());
						msg.setTo(to);
						msg.setFrom(emailSender.getUsername(), emailSender.getPersonal());
						msg.setText(tpl.getText(), true);
					}
				});
			}
		}
	}

	@Autowired
	private CmsSiteMng cmsSiteMng;
}
